#include "ImageView.h"
#include "ToolPane.h"
//(*InternalHeaders(ImageView)
#include <wx/intl.h>
#include <wx/string.h>
#include <algorithm>
//*)
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
#include "set.h"
#include "global.h"
//(*IdInit(ImageView)
//*)

BEGIN_EVENT_TABLE(ImageView,wxPanel)
	EVT_PAINT(ImageView::OnPaint)
	EVT_LEFT_DOWN(ImageView::OnLeftDown)
	EVT_LEFT_UP(ImageView::OnLeftUp)
	EVT_MOTION(ImageView::OnMove)
	EVT_ERASE_BACKGROUND(ImageView::OnBackground)
	EVT_ACTIVATE(ImageView::OnActive)
END_EVENT_TABLE()

void ImageView::OnActive(wxActivateEvent &event)
{
    int zoom = GetZoom();
    int w = m_pBmp->GetWidth();
    int h = m_pBmp->GetHeight();
    SetVirtualSize(w*zoom,h*zoom);
    SetScrollRate( 10, 10);
    Refresh();
}

void ImageView::OnBackground(wxEraseEvent &event)
{
    //event.Skip();
}
ImageView::ImageView(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
    m_pBmp = NULL;
	//(*Initialize(ImageView)
	Create(parent, id, pos, size, wxTAB_TRAVERSAL, _T("id"));
	//*)
	m_selRect.SetX(0);
	m_selRect.SetY(0);
	m_selRect.SetWidth(0);
	m_selRect.SetHeight(0);
	m_drawSelRect = false;
}

void ImageView::SetImage(wxString &fileName)
{
    m_imageName = fileName;
    //m_bmp.LoadFile(fileName,wxBITMAP_TYPE_PNG);
    m_pBmp = FindBmp(fileName);
}
void ImageView::Draw(wxDC &dc)
{
    int zoom = GetZoom();
    dc.SetBrush(*wxWHITE_BRUSH);
    dc.SetPen(*wxWHITE_PEN);
    //dc.DrawRectangle(GetClientSize());
    //if(m_pBmp != NULL)
        //dc.DrawBitmap(*m_pBmp,0,0);
    if(m_pBmp != NULL)
    {
        int w = m_pBmp->GetWidth();
        int h = m_pBmp->GetHeight();
        if((m_virtualSize.GetWidth() != w*zoom) || (m_virtualSize.GetHeight() != h*zoom))
        {
            m_virtualSize.SetWidth(w*zoom);
            m_virtualSize.SetHeight(h*zoom);
            SetVirtualSize(w*zoom,h*zoom);
            SetScrollRate( 10, 10);
            Refresh();
        }

        wxMemoryDC *memdc = FindMemoryDC(m_pBmp);
        //int w,h;
        //memdc->GetSize(&w,&h);
        dc.StretchBlit(0,0,w*zoom,h*zoom,memdc,0,0,w,h);
    }
    if(ShowGird())
    {
        wxSize gridSize = GetGridSize()*zoom;
        wxSize size = GetClientSize()*zoom;
        dc.SetPen(*wxGREY_PEN);
        for(int i = 0; i < size.GetWidth()/gridSize.GetWidth(); i++)
        {
            dc.DrawLine(i*gridSize.GetWidth(),0,i*gridSize.GetWidth(),size.GetHeight());
        }
        for(int i = 0; i < size.GetHeight()/gridSize.GetHeight(); i++)
        {
            dc.DrawLine(0,i*gridSize.GetHeight(),size.GetWidth(),i*gridSize.GetHeight());
        }
    }
}
void ImageView::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);

    DoPrepareDC(dc);
    wxSize clientSize = GetClientSize();
    int w = m_pBmp->GetWidth();
    int h = m_pBmp->GetHeight();
    int zoom = GetZoom();
    if(clientSize.GetWidth() < w*zoom)
        clientSize.SetWidth(w*zoom);
    if(clientSize.GetHeight() < h*zoom)
        clientSize.SetHeight(h*zoom);
    wxBitmap bmp(clientSize.GetWidth(),clientSize.GetHeight());
    wxMemoryDC memDC(bmp);
    //DoPrepareDC(memDC);
    Draw(memDC);
    if((m_selRect.GetWidth() > 0) && (m_selRect.GetHeight() > 0))
    {
        memDC.SetBrush(*wxTRANSPARENT_BRUSH);
        memDC.SetPen(*wxRED_PEN);
        memDC.DrawRectangle(m_selRect);
    }
    dc.Blit(0,0,clientSize.GetWidth(),clientSize.GetHeight(),&memDC,0,0);
}

ImageView::~ImageView()
{
	//(*Destroy(ImageView)
	//*)
}

void ImageView::OnLeftDown(wxMouseEvent &event)
{
    int zoom = GetZoom();
    int x;
    int y;
    CalcUnscrolledPosition(event.GetX(),event.GetY(),&x,&y);

    if((m_pBmp == NULL) || (x > m_pBmp->GetWidth()*zoom) || (y > m_pBmp->GetHeight()*zoom))
        return;

    wxSize size = GetGridSize()*zoom;
    if(SnapGrid())
    {
        m_selRect.SetX(x/size.GetWidth()*size.GetWidth());
        m_selRect.SetY(y/size.GetHeight()*size.GetHeight());
    }
    else
    {
        m_selRect.SetX(x);
        m_selRect.SetY(y);
    }
    m_selRect.SetWidth(size.GetWidth());
    m_selRect.SetHeight(size.GetHeight());
    m_drawSelRect = true;
}

void ImageView::OnLeftUp(wxMouseEvent &event)
{
    m_drawSelRect = false;
    SetSelImage(true);
    Refresh();
}

void ImageView::OnMove(wxMouseEvent &event)
{
    if(!m_drawSelRect)
        return;
    int zoom = GetZoom();
    int x;
    int y;
    CalcUnscrolledPosition(event.GetX(),event.GetY(),&x,&y);
    if((x < m_selRect.GetX()) || (y < m_selRect.GetY()))
        return;

    if(m_pBmp == NULL)
        return;
    if(x > m_pBmp->GetWidth()*zoom)
        x = m_pBmp->GetWidth()*zoom;
    if(y > m_pBmp->GetHeight()*zoom)
        y = m_pBmp->GetHeight()*zoom;

    wxSize size = GetGridSize()*zoom;
    if(SnapGrid())
    {
        bool modx = x%size.GetWidth() > 0;
        if(modx)
            x = (x/size.GetWidth()+1)*size.GetWidth();
        else
            x = x/size.GetWidth()*size.GetWidth();
        bool mody = y%size.GetHeight() > 0;
        if(mody)
            y = (y/size.GetHeight()+1)*size.GetHeight();
        else
            y = y/size.GetHeight()*size.GetHeight();
    }
    int w,h;
    w = x - m_selRect.GetX();
    h = y - m_selRect.GetY();
    m_selRect.SetWidth(w);
    m_selRect.SetHeight(h);

    wxClientDC dc(this);
    DoPrepareDC(dc);

    wxSize clientSize = GetClientSize();
    w = m_pBmp->GetWidth();
    h = m_pBmp->GetHeight();
    if(clientSize.GetWidth() < w*zoom)
        clientSize.SetWidth(w*zoom);
    if(clientSize.GetHeight() < h*zoom)
        clientSize.SetHeight(h*zoom);

    wxBitmap bmp(clientSize.GetWidth(),clientSize.GetHeight());
    wxMemoryDC memDC(bmp);
    Draw(memDC);
    memDC.SetBrush(*wxTRANSPARENT_BRUSH);
    memDC.SetPen(*wxRED_PEN);
    memDC.DrawRectangle(m_selRect);
    dc.Blit(0,0,clientSize.GetWidth(),clientSize.GetHeight(),&memDC,0,0);
}

SSelImage *ImageView::GetSelImage()
{
    if((m_selRect.GetWidth() == 0) || (m_selRect.GetHeight() == 0))
        return NULL;
    static SSelImage selImage;
    selImage.name = m_imageName;
    selImage.rect = m_selRect;
    wxRect &rect = selImage.rect;
    int zoom = GetZoom();
    rect.SetX(rect.x/zoom);
    rect.SetY(rect.y/zoom);
    rect.SetWidth(rect.GetWidth()/zoom);
    rect.SetHeight(rect.GetHeight()/zoom);
    return &selImage;
}
